// protocol-codec.js

// 协议注册表
const protocolRegistry = new Map();

/**
 * 注册协议处理器
 * @param {number} protocolId - 协议号
 * @param {string} messageType - protobuf消息类型
 * @param {function} handler - 处理回调函数
 */
function registerProtocol(protocolId, messageType, handler) {
    protocolRegistry.set(protocolId, {
        messageType,
        handler
    });
}

/**
 * 取消注册协议处理器
 * @param {number} protocolId - 协议号
 */
function unregisterProtocol(protocolId) {
    protocolRegistry.delete(protocolId);
}

/**
 * 清空所有协议注册
 */
function clearProtocolRegistry() {
    protocolRegistry.clear();
}

/**
 * 将数据打包成二进制格式发送
 * @param {object} data - 要打包的数据对象
 * @param {string} data.protocol - 'protobuf' 或 'custom'
 * @param {object} [data.payload] - protobuf 的数据体
 * @param {string} [data.messageType] - protobuf 的消息类型
 * @param {number} [data.protocolId] - 协议号
 * @param {string} [data.rawData] - custom 协议的原始字符串数据
 * @param {object} [protoRoot] - 已加载的 protobuf root 对象
 * @param {function} [logCallback] - 日志回调函数
 * @returns {Buffer} - 打包后的 Buffer
 */
function pack({ protocol, payload, messageType, protocolId, rawData }, protoRoot, logCallback) {
    if (protocol === 'protobuf') {
        if (!protoRoot) throw new Error('Protobuf .proto 文件未加载。');
        const MessageType = protoRoot.lookupType(messageType);
        const errMsg = MessageType.verify(payload);
        if (errMsg) throw new Error(`Protobuf 数据验证失败: ${errMsg}`);
        const message = MessageType.create(payload);
        const body = MessageType.encode(message).finish();

        const protoIdInt = protocolId || 0;
        const totalLength = 4 + 4 + body.length;

        const buffer = Buffer.alloc(totalLength);
        buffer.writeInt32BE(body.length, 0);
        buffer.writeInt32BE(protoIdInt, 4);
        body.copy(buffer, 8);
        
        // 输出到日志区域
        if (logCallback) {
            logCallback(`[Pack] 协议号: ${protoIdInt}, Body长度: ${body.length}字节`, 'info');
            logCallback(`[Pack] 完整数据包: ${buffer.toString('hex')}`, 'info');
        }
        
        return buffer;
    }

    if (protocol === 'custom') {
        // 对于自定义协议，可以直接返回字符串的 Buffer
        return Buffer.from(rawData);
    }

    // 其他协议或未指定，返回空 Buffer 或抛出错误
    throw new Error(`不支持的协议类型用于打包: ${protocol}`);
}

/**
 * 从 Buffer 中解包数据
 * @param {Buffer} buffer - 接收到的原始 Buffer 数据
 * @param {function} onData - 回调函数，用于处理解包后的数据
 * @param {object} [protoRoot] - protobuf root对象，用于解码
 * @param {function} [logCallback] - 日志回调函数
 * @param {string} [receiveMessageType] - 用户选择的接收消息类型（仅用于UI过滤）
 * @param {string} [receiveProtocolId] - 用户选择的接收协议号（仅用于UI过滤）
 * @returns {Buffer} - 返回剩余未处理完的 Buffer
 */
function unpack(buffer, onData, protoRoot, logCallback, receiveMessageType, receiveProtocolId) {
    let currentBuffer = buffer;
    while (currentBuffer.length >= 8) {
        const totalLength = currentBuffer.readInt32BE(0);

        if (currentBuffer.length >= totalLength + 8) {
            const protocolId = currentBuffer.readInt32BE(4);
            const body = currentBuffer.slice(8, totalLength + 8);
            
            if (logCallback) {
                logCallback(`[Unpack] 协议号: ${protocolId}, Body长度: ${body.length}字节`, 'info');
            }
            
            let decodedData = { protocolId, body };
            
            if (protoRoot) {
                let decoded = false;
                
                try {
                    // 检查是否有注册的协议处理器
                    const registeredProtocol = protocolRegistry.get(protocolId);
                    logCallback(`协议数量: ${protocolRegistry.size} 当前协议号: ${protocolId} 是否注册: ${registeredProtocol ? '是' : '否'}`, 'info');
                    if (registeredProtocol) {
                        try {
                            const MessageType = protoRoot.lookupType(registeredProtocol.messageType);
                            const message = MessageType.decode(body);
                            const decodedObject = MessageType.toObject(message, { 
                                defaults: true,
                                longs: String,
                                enums: String,
                                bytes: String
                            });
                            
                            decodedData = {
                                protocolId,
                                messageType: MessageType.name,
                                data: decodedObject
                            };
                            
                            decoded = true;
                            if (logCallback) {
                                logCallback(`[Unpack] 使用注册协议 ${protocolId} -> ${registeredProtocol.messageType} 解码成功`, 'success');
                            }
                            
                            // 调用注册的处理器
                            if (registeredProtocol.handler) {
                                try {
                                    registeredProtocol.handler(decodedData);
                                } catch (handlerError) {
                                    if (logCallback) {
                                        logCallback(`[Unpack] 协议处理器执行失败: ${handlerError.message}`, 'error');
                                    }
                                }
                            }
                        } catch (error) {
                            if (logCallback) {
                                logCallback(`[Unpack] 注册协议解码失败: ${error.message}`, 'warning');
                            }
                        }
                    }
                    
                    // 如果没有注册的协议处理器，且用户指定了接收消息类型，尝试该类型
                    if (!decoded && receiveMessageType) {
                        try {
                            const MessageType = protoRoot.lookupType(receiveMessageType);
                            const message = MessageType.decode(body);
                            const decodedObject = MessageType.toObject(message, { 
                                defaults: true,
                                longs: String,
                                enums: String,
                                bytes: String
                            });
                            
                            decodedData = {
                                protocolId,
                                messageType: MessageType.name,
                                data: decodedObject
                            };
                            
                            decoded = true;
                            if (logCallback) {
                                logCallback(`[Unpack] 使用指定类型 ${MessageType.name} 解码成功`, 'success');
                            }
                        } catch (error) {
                            if (logCallback) {
                                logCallback(`[Unpack] 指定类型 ${receiveMessageType} 解码失败: ${error.message}`, 'warning');
                            }
                        }
                    }
                    
                    if (!decoded && logCallback) {
                        logCallback(`[Unpack] 协议号 ${protocolId} 未注册处理器，使用原始格式`, 'warning');
                    }
                } catch (error) {
                    if (logCallback) {
                        logCallback(`[Unpack] Protobuf解码失败: ${error.message}`, 'error');
                    }
                }
            }
            
            if (logCallback) {
                logCallback(`[Debug] 准备调用 onData 回调，数据: ${JSON.stringify(decodedData)}`, 'info');
            }
            // 无论是否有注册处理器，都调用通用的onData回调
            onData(decodedData);
            currentBuffer = currentBuffer.slice(totalLength + 8);
        } else {
            break;
        }
    }
    return currentBuffer;
}

module.exports = {
    pack,
    unpack,
    registerProtocol,
    unregisterProtocol,
    clearProtocolRegistry,
};